package com.example.concurrency.cyclicbarrier;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

@Component
public class CyclicBarrierDemo
{
    private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 100,
            TimeUnit.SECONDS,
            new LinkedBlockingDeque<>(5),
            new ThreadPoolExecutor.DiscardPolicy());

    private AtomicInteger running = new AtomicInteger();

    private AtomicInteger count = new AtomicInteger(0);

    CyclicBarrier barrier = new CyclicBarrier(5, () ->
    {
        System.out.println("count: " + count);
        running.compareAndSet(1, 0);
    });

    private List<Worker> workerList = new ArrayList<>();

    @PostConstruct
    public void init()
    {
        workerList = new ArrayList<>();
        for (int i = 0; i < 5; i++)
        {
            Worker worker = new Worker("Thead1", barrier, (i + 1) * 2);
            workerList.add(worker);
        }
    }

    @Scheduled(cron = "${task.device_syn_time:0/5 * * * * ? }")
    public void doTask()
    {
        if (running.compareAndSet(0, 1))
        {
            count.incrementAndGet();
            workerList.forEach(executor::execute);
        } else
        {
            System.out.println("任务正则执行。。。。。。");
        }
    }

    private static class Worker implements Runnable
    {
        private String name = "";

        private CyclicBarrier cyclicBarrier;

        private long sleepTime;

        public Worker(String name, CyclicBarrier cyclicBarrier, long sleepTime)
        {
            this.name = name;
            this.cyclicBarrier = cyclicBarrier;
            this.sleepTime = sleepTime;
        }

        @Override
        public void run()
        {
            System.out.println("name: " + name + ">>>>start");
            try
            {
                TimeUnit.SECONDS.sleep(sleepTime);
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            }
            try
            {
                cyclicBarrier.await();
            } catch (InterruptedException | BrokenBarrierException e)
            {
                e.printStackTrace();
            }
            System.out.println("name: " + name + ">>>>end");
        }
    }
}
